package com.hcj.springcloud;

import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Test;

import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.TreeMap;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * jdk8 新特性
 * 新引入函数式编程方式
 */
@Slf4j
public class Jdk8 {

    /**
     * Consumer是一个函数式编程接口； 顾名思义，Consumer的意思就是消费，即针对某个东西我们来使用它，因此它包含有一个有输入而无输出的accept接口方法；
     * 除accept方法，它还包含有andThen这个方法
     */

    @Test
    public void consumerTest() {
        Consumer f = System.out::println;
        Consumer f2 = (p1) -> {
            log.info("参数: {};", p1);
        };
        // 从左算到右
        f.andThen(f2).andThen(f).andThen(f).accept("A");

        // 输出结果
        // A
        // 14:22:05.011 [main] INFO com.hcj.springcloud.Jdk8 - 参数: A;
        // A
        // A
    }


    /**
     * Function也是一个函数式编程接口；它代表的含义是“函数”，而函数经常是有输入输出的，因此它含有一个apply方法，包含一个输入与一个输出；
     * 除apply方法外，它还有compose与andThen及indentity三个方法
     */
    @Test
    public void functionTest() {
        Function<Integer, Integer> f = s -> {
            s = s + 1;
            return s;
        };
        Function<Integer, Integer> f1 = s -> s * 2;


        /**
         * compose 从右算到左。。。
         * Integer a = f1.apply(2);
         * f.apply(a);
         */
        System.out.println(f.compose(f1).apply(2));

        System.out.println(f1.compose(f).apply(2));

        System.out.println(f1.compose(f).compose(f1).apply(2));
        /**
         * andThen 从左算到右。。。
         * Integer a = f.apply(2);
         * f1.apply(a);
         */
        System.out.println(f.andThen(f1).apply(2));
        // identity方法会返回一个不进行任何处理的Function，即输出与输入值相等；
        System.out.println(Function.identity().apply(2));
    }


    /**
     * Predicate为函数式接口，predicate的中文意思是“断定”，即判断的意思，判断某个东西是否满足某种条件；
     * 因此它包含test方法，根据输入值来做逻辑判断，其结果为True或者False。
     */
    @Test
    public void predicateTest() {
        Predicate<String> p = o -> {
            return o.equals("o");
        };
        Predicate<String> g = o -> o.startsWith("o");
        /**
         * 与 p和g同时为true,则为true
         */
        Assert.assertTrue(p.and(g).test("o"));
        /**
         * 或 p OR g ，一个为true,则为true
         */
        Assert.assertTrue(p.or(g).test("o"));
        /**
         * 非 如当调用p.test("test")为True时，调用p.negate().test("test")就会是False；
         */
        Assert.assertFalse(p.negate().test("o"));
    }


    @Test
    public void flatMapTest() {
        Stream<String> s = Stream.of("a d", "b", "c");
        s.flatMap(x -> Stream.of(x.split(" "))).forEach(System.out::println);
        System.out.println("s = " + s);
        Stream<String> ss = Stream.of("a d", "b", "c");
        ss.map(x -> x.split(" ")).flatMap(Arrays::stream).collect(Collectors.toList()).forEach(System.out::println);
    }

    @Test
    public void groupByTest() {
        Stream<String> s = Stream.of("5a", "1b", "c", "d", "d");
        // 1.先分组， 2.计算个数 3.映射成有序的map
        TreeMap<String, Long> treeMap = s.collect(Collectors.groupingBy(x -> x, TreeMap::new, Collectors.counting()));
        treeMap.forEach((k, v) -> System.out.println(k + "=" + v));
        log.info("first key = {}", treeMap.firstKey());
        log.info("last key = {}", treeMap.lastKey());
        log.info("lower key of c = {}", treeMap.lowerKey("c"));
        log.info("keySet = {}", treeMap.keySet());
        log.info("key 倒叙排 descendingKeySet = {}", treeMap.descendingKeySet());
        log.info("navigableKeySet = {}", treeMap.navigableKeySet());
        throw new AssertionError();
    }


}
